package middleware

import (
	"bytes"
	"io"
	"log"
	"os"
	"time"

	"github.com/gin-gonic/gin"

	"BookStack/pkg/utils"
)

// 自定义日志输出格式，避免显示文件名和行号
var logger = log.New(os.Stdout, "", 0)

// RequestLogger 请求日志中间件
func RequestLogger() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 开始时间
		startTime := time.Now()

		// 请求路由
		reqURI := c.Request.RequestURI

		// 请求方式
		reqMethod := c.Request.Method

		// 记录请求体
		var requestBody []byte
		if c.Request.Body != nil {
			requestBody, _ = io.ReadAll(c.Request.Body)
			// 恢复请求体，以便后续中间件和处理器能够读取
			c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
		}

		// 创建自定义ResponseWriter来捕获响应体
		bodyWriter := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		c.Writer = bodyWriter

		// 处理请求
		c.Next()

		// 结束时间
		endTime := time.Now()

		// 执行时间
		latencyTime := endTime.Sub(startTime)

		// 状态码
		statusCode := c.Writer.Status()

		// 请求IP
		clientIP := c.ClientIP()

		// 获取响应体
		responseBody := bodyWriter.body.String()

		// 记录错误请求
		if statusCode >= 400 {
			logger.Printf("[ERROR] %s %s %d %s", reqMethod, reqURI, statusCode, string(requestBody))
		}

		// 记录日志
		logger.Printf("[GIN] %s | %d | %s | %s | %s | %s | Response: %s",
			utils.FormatTime(endTime),
			statusCode,
			latencyTime.String(),
			clientIP,
			reqMethod,
			reqURI,
			responseBody,
		)

		// 记录慢请求
		if latencyTime > time.Second*3 {
			logger.Printf("[SLOW API] %s %s %s Response: %s",
				reqMethod,
				reqURI,
				latencyTime.String(),
				responseBody)
		}
	}
}

// bodyLogWriter 用于捕获响应体的自定义ResponseWriter
type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

// Write 重写Write方法，同时写入响应体和缓冲区
func (w *bodyLogWriter) Write(b []byte) (int, error) {
	w.body.Write(b)
	return w.ResponseWriter.Write(b)
}
